package com.webzavod.services;

import com.webzavod.model.Authority;
import com.webzavod.model.Order;
import com.webzavod.model.User;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: v.tsapaev
 * Date: 25.05.12
 * Time: 19:24
 * To change this template use File | Settings | File Templates.
 */
@Service
@Transactional
public class OrderService {

    private static Logger LOG = LoggerFactory.getLogger(OrderService.class);

    @Autowired
    SessionFactory sessionFactory;

    @Autowired
    UserService userService;

    /**
     * create order for current user
     * @param order - order which create
     * @return order if created success
     */
    @CacheEvict(value = "orders", allEntries = true)
    public Order createOrder(Order order){
        String currentUsername = SecurityContextHolder.getContext().getAuthentication().getName();
        User user = userService.getUserByUsername(currentUsername);
        order.setOwner(user);
        sessionFactory.getCurrentSession().save(order);
        return order;
    }

    /**
     * @return all orders for current user. If role user is admin - return all orders
     */
    public List<Order> getOrdersForCurrentUser(){
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        User currentUser = userService.getUserByUsername(username);
        Set<Authority> authoritySet = currentUser.getAuthority();
        List<Order> orderList;
        LOG.info("current user = " + currentUser);
        Authority adminAuthority = new Authority("ROLE_ADMIN");
        if (authoritySet.contains(adminAuthority)){
            orderList =  sessionFactory.getCurrentSession()
                    .createQuery("from Order")
                    .list();
        } else {
            orderList =  sessionFactory.getCurrentSession()
                    .createQuery("from Order where owner = :user")
                    .setParameter("user", currentUser).list();
        }
        LOG.info("orderList = " + orderList);
        return orderList;
    }


    /**
     * find order for current user
     * @param orderId - order number
     * @return any exists order if current user is admin. for other role return order for current user
     */
    public Order findOrder(Integer orderId){
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        User currentUser = userService.getUserByUsername(username);
        Set<Authority> authoritySet = currentUser.getAuthority();
        Order order;
        LOG.info("current user = " + currentUser);
        Authority adminAuthority = new Authority("ROLE_ADMIN");
        if (authoritySet.contains(adminAuthority)){
            order = getOrderById(orderId);
        } else {
            order = (Order)sessionFactory.getCurrentSession()
                    .createQuery("from Order where orderId = :orderId and owner = :currentUser")
                    .setParameter("orderId", orderId)
                    .setParameter("currentUser", currentUser)
                    .uniqueResult();
        }
        return order;
    }

    /**
     * @param orderId - order number
     * @return order by order number
     */
    @Cacheable(value = "orders")
    private Order getOrderById(Integer orderId){
        return (Order)sessionFactory.getCurrentSession()
                .get(Order.class, orderId);
    }
}
